import os
from lib import *
from simulation import *

proj = Simulation("8-Bit-Computer", debug=False)

# = 时钟&总线 =
# ==========================================
proj.addChip("bus", BUS(8))        # 总线
proj.addChip("clk", Timer())       # 时钟  HLT
# 添加LED灯监视
proj.addChip(" bus LED", LedSet(8))
proj.bind(proj["bus"].pinOUT, proj[" bus LED"].pinIN)
proj.addChip(" clk LED", LedSet(2))
proj.bind(proj["clk"].pinOUT, proj[" clk LED"].pinIN)
# ==========================================

# = 寄存器 =
# ==========================================
# 寄存器A:主寄存器,数据和立即数都加载到寄存器A
proj.addChip("rega", Register(8))   # 寄存器A | AI  AO
proj.bind(proj["clk"].CLK, proj["rega"].CLK)
proj.bind(proj["bus"].pinOUT, proj["rega"].DAT)
proj.bind(proj["rega"].pinOUT, proj["bus"].pinIN, mode=2)
proj.addChip("rega LED", LedSet(8))
proj.bind(proj["rega"]._dat, proj["rega LED"].pinIN)

# 寄存器B:辅助寄存器,需要进行运算的数加载到寄存器B
proj.addChip("regb", Register(8))   # 寄存器B | BI
proj.bind(proj["clk"].CLK, proj["regb"].CLK)
proj.bind(proj["bus"].pinOUT, proj["regb"].DAT)
proj.bind(proj["regb"].pinOUT, proj["bus"].pinIN, mode=2)
proj.addChip("regb LED", LedSet(8))
proj.bind(proj["regb"]._dat, proj["regb LED"].pinIN)

# 寄存器I:指令寄存器,高4位指令传入控制指令译码,低四位为立即数
proj.addChip("regi", Register(8))   # 寄存器I | II  IO
proj.bind(proj["clk"].CLK, proj["regi"].CLK)
proj.bind(proj["bus"].pinOUT, proj["regi"].DAT)
proj.bind(proj["regi"].pinOUT@[4,8], proj["bus"].pinIN@[4,8], mode=2)
proj.addChip("regi LED", LedSet(8, "<ledb>"))
proj.bind(proj["regi"]._dat, proj["regi LED"].pinIN)

# 寄存器O:显示寄存器,仅存入需要显示的数据,保证显示器能保持数据
proj.addChip("rego", Register(8))   # 寄存器O | OI
proj.bind(proj["clk"].CLK, proj["rego"].CLK)
proj.bind(proj["bus"].pinOUT, proj["rego"].DAT)

# 寄存器F:
proj.addChip("regf", Register(2))   # 寄存器F | FI
proj.bind(proj["clk"].CLK, proj["rego"].CLK)
proj.addChip("regf LED", LedSet(2))
proj.bind(proj["regf"]._dat, proj["regf LED"].pinIN)
# ==========================================

# = 计算模块 =
# ==========================================
proj.addChip("alu", ALU(8))         # 计算器 | EO  SU
proj.bind(proj["rega"]._dat, proj["alu"].DAT1)
proj.bind(proj["regb"]._dat, proj["alu"].DAT2)
proj.bind(proj["alu"].CF, proj["regf"].DAT@[0])
proj.addChip("zfs", NOR(8))
proj.bind(proj["zfs"].pinOUT, proj["regf"].pinIN@[1])
proj.bind(proj["alu"].pinOUT@[1,9], proj["bus"].pinIN, mode=2)
proj.addChip(" alu LED", LedSet(8))
proj.bind(proj["alu"]._dat, proj[" alu LED"].pinIN)
# ==========================================

# = 内存 =
# ==========================================
proj.addChip("mem", Memory(4, 8))   # 内存  AI | MI | MO
proj.bind(proj["bus"].pinOUT, proj["mem"].DAT)
proj.bind(proj["bus"]@[4,8], proj["mem"].ADDR)
proj.bind(proj["mem"].pinOUT, proj["bus"].pinIN, mode=2)
proj.addChip(" mem LED", LedSet(8))
proj.bind(proj["mem"]._dat, proj[" mem LED"].pinIN)
# =====================
# = 对内存进行编程 加法 =
# =====================
try : import program
except : 
    # proj["mem"].prog_mem(0b0000, 0b00011110)    # 00  LDA 14
    # proj["mem"].prog_mem(0b0001, 0b00101111)    # 01  ADD 15
    # proj["mem"].prog_mem(0b0010, 0b11100000)    # 02  OUT
    # proj["mem"].prog_mem(0b0011, 0b11110000)    # 03  HLT
    # proj["mem"].prog_mem(0b1110, 0b00101101)    # 14  45
    # proj["mem"].prog_mem(0b1111, 0b01101011)    # 15  107
# =====================
    proj["mem"].prog_mem(0x0, 0b01010001)    # 00 LDI  1
    proj["mem"].prog_mem(0x1, 0b00101110)    # 01 ADD 14
    proj["mem"].prog_mem(0x2, 0b01001110)    # 02 STA 14
    proj["mem"].prog_mem(0x3, 0b00101111)    # 03 ADD 15
    proj["mem"].prog_mem(0x4, 0b10001000)    # 04 JC   8
    proj["mem"].prog_mem(0x5, 0b11100000)    # 05 OUT
    proj["mem"].prog_mem(0x6, 0b01001111)    # 06 STA 15
    proj["mem"].prog_mem(0x7, 0b01100000)    # 07 JMP  0
    proj["mem"].prog_mem(0x8, 0b11110000)    # 08 HLT
    proj["mem"].prog_mem(0xe, 0b00000000)    # 14 0
    proj["mem"].prog_mem(0xf, 0b00000000)    # 15 0
# ==========================================
else : proj["mem"].load_mem(program.prog())

# = 指令计数器 =
# ==========================================
proj.addChip("ic", Counter(4))
proj.bind(proj["clk"].CLK, proj["ic"].CLK)
proj.bind(proj["bus"].pinOUT@[4,8], proj["ic"].DAT)
proj.bind(proj["ic"].pinOUT, proj["bus"].pinIN, mode=2)
proj.addChip("  ic LED", LedSet(4))
proj.bind(proj["ic"]._dat, proj["  ic LED"].pinIN)
# ==========================================

# = 微指令计数器 =
# ==========================================
proj.addChip("mc", Counter(3))
proj["mc"].EN(1)
proj.addChip("mcr", NOR(16))
proj.bind(proj["mcr"].pinOUT, proj["mc"].RST)
proj.bind(proj["clk"].NCLK, proj["mc"].CLK)
proj.addChip("  mc LED", LedSet(3))
proj.bind(proj["mc"]._dat, proj["  mc LED"].pinIN)
# ==========================================

# = 指令译码器 =
# ==========================================
proj.addChip("id", PROM(9, 16, "./lib/bin/8bit.bin"))
proj.bind(proj["regf"]._dat, proj["id"].pinIN@[0,2])
proj.bind(proj["regi"]._dat@[0,4], proj["id"].pinIN@[2,6])
proj.bind(proj["mc"]._dat, proj["id"].pinIN@[6,9])
proj.bind(proj["id"].pinOUT@[ 0], proj["clk"].HLT)      # HLT
proj.bind(proj["id"].pinOUT@[ 1], proj["mem"].AI)       # MI
proj.bind(proj["id"].pinOUT@[ 2], proj["mem"].RI)       # RI
proj.bind(proj["id"].pinOUT@[ 3], proj["mem"].RO)       # RO
proj.bind(proj["id"].pinOUT@[ 4], proj["regi"].EO)      # IO
proj.bind(proj["id"].pinOUT@[ 5], proj["regi"].EI)      # II
proj.bind(proj["id"].pinOUT@[ 6], proj["rega"].EI)      # AI
proj.bind(proj["id"].pinOUT@[ 7], proj["rega"].EO)      # IO
proj.bind(proj["id"].pinOUT@[ 8], proj["alu"].EO)       # EO
proj.bind(proj["id"].pinOUT@[ 9], proj["alu"].TYP@[2])  # SU
proj.bind(proj["id"].pinOUT@[10], proj["regb"].EI)      # BI
proj.bind(proj["id"].pinOUT@[11], proj["rego"].EI)      # OI
proj.bind(proj["id"].pinOUT@[12], proj["ic"].EN)        # CE
proj.bind(proj["id"].pinOUT@[13], proj["ic"].EO)        # CO
proj.bind(proj["id"].pinOUT@[14], proj["ic"].EI)        # J
proj.bind(proj["id"].pinOUT@[15], proj["regf"].EI)      # FI
# 使用指令译码器的输出来重置微指令计数器
proj.bind(proj["id"].pinOUT, proj["mcr"].pinIN)
proj.addChip("  id LED", LedSet(16))
proj.bind(proj["id"].pinOUT, proj["  id LED"].pinIN)
# ==========================================

# = 显示器 =
# ==========================================
proj.addChip("disp", Display(8))
proj["disp"].DIS(0)
proj.bind(proj["rego"]._dat, proj["disp"].DAT)
# ==========================================

proj.run()